﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Kinect;
using Microsoft.Samples.Kinect.KinectExplorer;
using Microsoft.Samples.Kinect.WpfViewers;
using KinectExplorer;

namespace ZeroTouchUI
{
    /// <summary>
    /// Interaction logic for GR2.xaml
    /// </summary>
    public partial class GR2 : UserControl
    {
        private KinectSensor kinect;
        private bool tracing = false;
        private int countdown = 3;
        private DispatcherTimer countdownTimer;
        private List<KinectSkeleton> skeletons;
        public MainWindow mainWindow;

        public GR2()
        {
            InitializeComponent();
        }

        public GR2(MainWindow mW)
        {
            InitializeComponent();
            mainWindow = mW;
            mainWindow.recognizer.Recognized += new GestureRecognizer.RecognizedEventHandler(recognizer_Recognized);
        }

        public KinectSensor Kinect
        {
            get
            {
                return this.kinect;
            }

            set
            {
                this.kinect = value;
                this.colorViewer.Kinect = this.kinect;
                this.KinectSkeletonViewerOnColor.Kinect = this.kinect;
            }
        }

        public class StopRecordingTimer : System.Timers.Timer
        {
            public List<KinectSkeleton> oldSkeletons;
        }

        private delegate void StopRecordingDelegate();

        private void StopRecording(List<KinectSkeleton> skeletons)
        {
            foreach (KinectSkeleton skeleton in skeletons)
            {
                skeleton.leftTracing = false;
                skeleton.rightTracing = false;
                skeleton.counter = 0;
            }

            this.tracing = false;
        }

        private void recordButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Button button = (Button)sender;
            skeletons = new List<KinectSkeleton>
                {
                    KinectSkeletonViewerOnColor.skeletonCanvas1,
                    KinectSkeletonViewerOnColor.skeletonCanvas2,
                    KinectSkeletonViewerOnColor.skeletonCanvas3,
                    KinectSkeletonViewerOnColor.skeletonCanvas4,
                    KinectSkeletonViewerOnColor.skeletonCanvas5,
                    KinectSkeletonViewerOnColor.skeletonCanvas6
                };

            if (this.tracing)
            {
                recordButton.Content = "Record";
                StopRecording(skeletons);
            }
            else
            {
                recordButton.Content = "3";
                countdownTimer = new DispatcherTimer();
                countdownTimer.Interval = new TimeSpan(0, 0, 1);
                countdownTimer.Tick += new EventHandler(CountdownTimerStep);
                countdownTimer.Start();
            }
        }

        private void CountdownTimerStep(object sender, EventArgs e)
        {
            if (countdown > 1)
            {
                countdown--;
                this.Dispatcher.BeginInvoke(new StopRecordingDelegate(() => recordButton.Content = countdown.ToString()));
            }
            else
            {
                countdownTimer.Stop();
                countdown = 3;
                recordButton.Content = "Stop";
                foreach (KinectSkeleton skeleton in skeletons)
                {
                    if (skeleton.rightGesture != null)
                    {
                        skeleton.rightGesture.Clear();
                    }
                    if (skeleton.leftGesture != null)
                    {
                        skeleton.leftGesture.Clear();
                    }

                    skeleton.rightGesture = new List<Point>();
                    skeleton.leftGesture = new List<Point>();
                    skeleton.leftTracing = (bool)leftGestureTracingSelection.IsChecked;
                    skeleton.rightTracing = (bool)rightGestureTracingSelection.IsChecked;
                }
                StopRecordingTimer timer = new StopRecordingTimer { oldSkeletons = skeletons };
                timer.Interval = 3000;
                timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
                timer.Start();

                this.tracing = true;
            }
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            StopRecordingTimer srt = (StopRecordingTimer)sender;
            this.Dispatcher.BeginInvoke(new StopRecordingDelegate(() => recordButton.Content = "Record"));
            StopRecording(srt.oldSkeletons);
            srt.Stop();
        }

        private string _recordButtonContent = "Record";
        public string RecordButtonContent
        {
            get
            {
                return _recordButtonContent;
            }

            set
            {
                _recordButtonContent = value;
                recordButton.Content = _recordButtonContent;
            }
        }

        private void recognizer_Recognized(object sender, RecognizedEventArgs e)
        {
            if (this.tracing)
            {
                this.Dispatcher.BeginInvoke(new StopRecordingDelegate(() => recordButton.Content = "Record"));
                StopRecording(skeletons);

                RejectedGesture rg = new RejectedGesture("Gesture " + e.gesture.Name + " was recognized during this recording.\n\n" +
                                                         "Please either erase " + e.gesture.Name + " or record a new gesture.");
                rg.Show();

                foreach (KinectSkeleton skeleton in skeletons)
                {
                    if (skeleton.rightGesture != null)
                    {
                        skeleton.rightGesture.Clear();
                    }
                    if (skeleton.leftGesture != null)
                    {
                        skeleton.leftGesture.Clear();
                    }
                }
            }
        }

        private void saveButton_Click(object sender, RoutedEventArgs e)
        {
            bool isRecorder = this.Parent.GetType().ToString().Contains("GestureRecorder");
            List<KinectSkeleton> skeletons = new List<KinectSkeleton>
                {
                    KinectSkeletonViewerOnColor.skeletonCanvas1,
                    KinectSkeletonViewerOnColor.skeletonCanvas2,
                    KinectSkeletonViewerOnColor.skeletonCanvas3,
                    KinectSkeletonViewerOnColor.skeletonCanvas4,
                    KinectSkeletonViewerOnColor.skeletonCanvas5,
                    KinectSkeletonViewerOnColor.skeletonCanvas6
                };
            foreach (KinectSkeleton skeleton in skeletons)
            {
                //Check for ambiguous cases before saving
                Gesture recognized = Dollar.Recognize(skeleton.leftGesture, skeleton.rightGesture, 0.55);
                if (recognized != null)
                {
                    RejectedGesture rg = new RejectedGesture("The gesture you have recorded has a high risk of being confused with " +
                                                              recognized.Name + ".\n\nPlease either erase " + recognized.Name +
                                                              " or record a new gesture.");
                    rg.ShowDialog();
                    return;
                }

                if ((skeleton.leftGesture != null && skeleton.leftGesture.Count > 0) ||
                    (skeleton.rightGesture != null && skeleton.rightGesture.Count > 0))
                {
                    skeleton.leftGesture = Dollar.Resample(skeleton.leftGesture);
                    skeleton.rightGesture = Dollar.Resample(skeleton.rightGesture);
                    if (skeleton.leftGesture != null && skeleton.leftGesture.Count > 0)
                    {
                        skeleton.leftGesture = Dollar.ScaleWithSharpen(skeleton.leftGesture);
                        skeleton.leftGesture = Dollar.TranslateToOrigin(skeleton.leftGesture);
                    }
                    if (skeleton.rightGesture != null && skeleton.rightGesture.Count > 0)
                    {
                        skeleton.rightGesture = Dollar.ScaleWithSharpen(skeleton.rightGesture);
                        skeleton.rightGesture = Dollar.TranslateToOrigin(skeleton.rightGesture);
                    }
                }

                if (skeleton.leftGesture != null && skeleton.leftGesture.Count > 0 &&
                    skeleton.rightGesture != null && skeleton.rightGesture.Count > 0)
                {
                    if (isRecorder)
                    {
                        ((GestureRecorder)this.Parent).leftGesture = skeleton.leftGesture;
                        ((GestureRecorder)this.Parent).rightGesture = skeleton.rightGesture;
                    }
                }
                else
                {
                    if (skeleton.leftGesture != null && skeleton.leftGesture.Count > 0)
                    {
                        if (isRecorder)
                        {
                            ((GestureRecorder)this.Parent).leftGesture = skeleton.leftGesture;
                        }
                    }
                    if (skeleton.rightGesture != null && skeleton.rightGesture.Count > 0)
                    {
                        if (isRecorder)
                        {
                            ((GestureRecorder)this.Parent).rightGesture = skeleton.rightGesture;
                        }
                    }
                }
                
            }

            if (isRecorder)
            {
                ((GestureRecorder)this.Parent).OnSaved(new EventArgs());
            }
        }
    }
}
